<script setup lang="ts">
import { nextTick, ref, watch, reactive, computed, unref, defineAsyncComponent } from 'vue'
import { useRoute } from 'vue-router'
import { useBaseApi, useBaseFileApi } from '@/api/base'
import { assign, clone, isArray, isNumber, toArrayTree } from 'xe-utils'
import { getColumnTips, getNotEmpty } from '@/utils/custom'
import { dayjs, ElLoadingService, ElMessage, ElMessageBox } from 'element-plus'
import { useWfApi } from '@/api/wf'
import { useBaseRoleApi } from '@/api/base/role'
import mittBus from '@/utils/mitt'
import type { AxiosRequestConfig } from 'axios'
import { themeConfig } from '@/storage'
import { storeToRefs } from 'pinia'
import { useAppState } from '@/stores/appState'
import { isGridRowId } from '@/utils'
import { readExcelFile } from '@/utils/importExcel'
import {
  onComponentServerFetch,
  onInitApiData,
  onInitDicData,
  setFormDefaultParams,
  type StateInterface
} from '@/views/components/form/libs'
import {
  columnFilterMethod,
  formatColRows,
  initFooterMethod,
  initFormatColumns,
  initFormatTabHead,
  initGridProps,
  removeGridColumns,
  setGridColumns
} from '@/views/components/grid/libs'
import {
  type VxeGridConstructor,
  type VxeGridDefines,
  type VxeGridInstance,
  type VxeGridProps,
  type VxeTableEvents,
  type VxeToolbarInstance,
  type VxeToolbarProps
} from 'vxe-table'
import type {
  BusinessUIAction,
  BusinessUIColumnType,
  BusinessUIFile,
  BusinessUIFormType,
  BusinessUIQueryType,
  BusinessUITableType,
  DicType,
  WorkflowDesignRow
} from '@/types/custom'
import { readerWordData } from '@/utils/exportWord'
import type { Fn } from '@vueuse/core'

const TemplateQuery = defineAsyncComponent(
  () => import('@/views/components/form/TemplateQuery.vue')
)
const TemplateFormDialog = defineAsyncComponent(
  () => import('@/views/components/form/TemplateFormDialog.vue')
)
const TemplateGridDialog = defineAsyncComponent(
  () => import('@/views/components/grid/TemplateGridDialog.vue')
)

interface Props {
  params?: TypedAny
  uiForm?: BusinessUIFormType
  uiTable?: BusinessUITableType
  uiQuery?: BusinessUIQueryType
  uiActions?: BusinessUIAction[]
  wfDesign?: WorkflowDesignRow
  dicTable?: DicType[]
  dicQuery?: DicType[]
  toolbarConfig?: VxeToolbarProps
  insert?: boolean
  height?: number | string
  boxShadow?: boolean
  emptyText?: string
  ready?: (value: number) => void
  pageSize?: number
  disabled?: boolean
  showActions?: string[]
}

const modelValue = defineModel<boolean | undefined>()

const props = withDefaults(defineProps<Props>(), {
  boxShadow: true
})

const emit = defineEmits(['close', 'fetch', 'radio-change'])

const route = useRoute()

let defaultCols: BusinessUIColumnType[] = []

// 基础接口
const { CustomRequest } = useBaseApi()
const { WorkFlowRoleSetUsers } = useWfApi()
const { WorkFlowRuingStart, WorkFlowRuingDel } = useWfApi()

// 其他接口
const { PutBaseRoleSetUsers } = useBaseRoleApi()
const { GetBaseFile, GetBaseFileDown } = useBaseFileApi()
const { mobile } = storeToRefs(useAppState())

// 加载中
const btnLoading = ref(false)
// 查询栏
const queryRef = ref()
// 表格
const gridRef = ref<VxeGridInstance>()
// 表格工具栏
const toolbarRef = ref<VxeToolbarInstance>()
// 表格配置
const gridOptions = ref<VxeGridProps<TypedAny>>({})
// 弹窗表单
const formDialogRef = ref()
// 弹窗表格
const gridDialogRef = ref()
// 表格分页
const gridPage = reactive({
  total: 0,
  page: 1,
  pageSize: props.pageSize || 50
})
// 当前查询栏参数
let queryParams: TypedAny | undefined
// 当前row
let currentRow: TypedAny | undefined
// 当前按钮
let currentAction: BusinessUIAction | undefined
// 顶部表格按钮偏移量
const rightSpacing = computed(() => {
  const config: TypedAny = props.toolbarConfig || {}

  // 移除表格自带的刷新
  delete config.refresh

  const { globalComponentSize } = unref(themeConfig)
  let length = 0
  for (const k in config) {
    if (!['enabled', 'zoom'].includes(k) && config[k]) {
      length += 1
    }
  }
  let size = 31
  if (globalComponentSize === 'mini') {
    size = 31
  } else if (globalComponentSize === 'default') {
    size = 35
  } else if (globalComponentSize === 'large') {
    size = 38
  }
  return length * size
})
// 需要删除rows
const deleteMap = new Map([])

/**
 * 主键
 */
const keyField = computed(() => props.uiTable?.default_value_parse.keyField || 'id')

// 内嵌按钮
const embeddedUIActions = computed(() => {
  return props.uiActions?.filter((f) => !f.global) || []
})

/**
 * 打开确认框
 */
const openMessageBox = (): Promise<Fn | undefined> => {
  if (!currentAction) return Promise.reject(false)
  const actionName = currentAction.name
  const tips = getColumnTips(props.uiTable?.columns || [], currentRow)
  return new Promise((resolve) => {
    ElMessageBox({
      title: '提示框',
      message: `确认要${actionName}${tips ? `《${tips}》` : ''}？`,
      showCancelButton: true,
      confirmButtonText: `确认${actionName}`,
      cancelButtonText: '取消',
      type: 'warning',
      beforeClose: (action, instance, done) => {
        if (action === 'confirm') {
          instance.confirmButtonLoading = true
          instance.confirmButtonText = `${actionName}中...`
          // callback().then(() => {
          //   instance.confirmButtonLoading = false
          //   done()
          // })
          resolve(done)
        } else {
          done()
        }
      }
    })
      .then(() => {
        onFetch()
      })
      .catch(() => ElMessage.info('已取消'))
  })
}

/**
 * 初始化表格属性
 */
const initGridOptions = async () => {
  if (!props.uiTable) return Promise.reject('没有配置表格')

  // 格式化表格配置
  gridOptions.value = initGridProps({
    uiForm: props.uiForm,
    uiTable: props.uiTable,
    disabled: props.disabled,
    filename: route.meta.title,
    exportConfig: {
      remote: true,
      exportMethod: async (option) => {
        const { $table, options } = option

        // 全量数据
        if (options.mode === 'all') {
          options.data = await onFetchAll()
        }

        // 必须关闭服务器端导出，不然会死循环
        options.remote = false

        // 导出
        return $table.exportData(options)
      }
    }
  })
  await nextTick(() => {
    // 将表格和工具栏进行关联
    const $grid = gridRef.value
    const $toolbar = toolbarRef.value
    if ($grid && $toolbar) {
      $grid.connect($toolbar)
    }
  })
}

/**
 * 合并请求参数配置
 */
const onFetchConfig = (uiTable: BusinessUITableType): TypedAny => {
  const { pagination } = uiTable
  const param = assign({}, props.params || {}, queryParams)
  return assign(clone(param, true), pagination ? gridPage : {})
}

/**
 * 查询
 */
const onFetch = async (slotParams?: TypedAny): Promise<TypedAny[]> => {
  if (!props.uiTable) return Promise.reject('没有表格配置')
  modelValue.value = true

  const { api, method, columns } = props.uiTable

  // const dicTable = props.dicTable || []

  const params = onFetchConfig(props.uiTable)

  const config: AxiosRequestConfig = {
    url: api,
    method
  }

  if (['get', 'delete'].includes(method.toLowerCase())) {
    config.params = assign({}, params, slotParams)
  } else {
    config.data = assign({}, params, slotParams)
  }

  const { data } = await CustomRequest(config)

  deleteMap.clear()

  // 总数
  if (data && isNumber(data.total)) gridPage.total = data.total

  if (data.tabHead) {
    // 多级表头
    const { cols, items } = await initFormatTabHead({
      data,
      params: props.params,
      uiForm: props.uiForm,
      uiTable: props.uiTable,
      dicTable: props.dicTable,
      uiActions: props.uiActions,
      disabled: props.disabled
    })
    // 初始化表尾合计
    initFooterMethod(unref(gridOptions), cols)
    // 格式化表列
    await reloadColumn(cols)
    // 赋值数据
    await nextTick(() => {
      defaultCols = cols
      formatColRows({
        rows: items,
        dicTable: props.dicTable,
        uiTable: props.uiTable,
        uiForm: props.uiForm
      })
      gridOptions.value.data = items
    })
  } else {
    // 一级表头
    const cols = await initFormatColumns({
      params: props.params,
      uiForm: props.uiForm,
      uiTable: props.uiTable,
      dicTable: props.dicTable,
      uiActions: props.uiActions,
      disabled: props.disabled
    })
    // 初始化表尾合计
    initFooterMethod(unref(gridOptions), cols)
    // 格式化表列
    await reloadColumn(cols)
    // 赋值数据
    await nextTick(() => {
      let rows = []
      if (isArray(data)) {
        rows = data
      } else if (data && isArray(data.items)) {
        rows = data.items
      }
      defaultCols = cols
      formatColRows({
        rows,
        dicTable: props.dicTable,
        uiTable: props.uiTable,
        uiForm: props.uiForm
      })
      // 树节点
      const treeCol = columns.find((s) => s.is_pid)
      if (treeCol) {
        gridOptions.value.data = toArrayTree(rows, {
          parentKey: treeCol.field,
          key: unref(keyField)
        })
      } else {
        gridOptions.value.data = rows
      }
    })
  }
  modelValue.value = false

  const list = gridOptions.value.data || []

  props.ready && props.ready(list.length)

  return list
}

/**
 * 导出全量数据
 */
const onFetchAll = async () => {
  if (!props.uiTable) return []
  const loadingInstance = ElLoadingService({
    fullscreen: true,
    text: '加载中...'
  })
  try {
    const list: any[] = []
    const count = Math.ceil(gridPage.total / 1000)

    const { api, method } = props.uiTable

    const config: AxiosRequestConfig = {
      url: api,
      method
    }
    const params = onFetchConfig(props.uiTable)
    params.pageSize = 1000
    for (let i = 1; i <= count; i++) {
      loadingInstance.text.value = `正在获取数据${i}/${count}，请耐心等待。`
      params.page = i

      if (['get', 'delete'].includes(method.toLowerCase())) {
        config.params = params
      } else {
        config.data = params
      }

      const { data } = await CustomRequest(config)

      const items = data ? data.items || [] : []
      list.push(...items)
    }
    formatColRows({
      rows: list,
      dicTable: props.dicTable,
      uiTable: props.uiTable,
      uiForm: props.uiForm
    })
    loadingInstance.close()
    return list
  } catch (e) {
    loadingInstance.close()
    return []
  }
}

/**
 * 工具栏查询
 * @param params
 */
const onToolFetch = (params?: TypedAny) => {
  queryParams = params || {}
  onFetch()
}

/**
 * 加载表格列
 * @param cols
 */
const reloadColumn = async (cols: BusinessUIColumnType[]) => {
  if (gridRef.value) await gridRef.value.reloadColumn(cols)
  return cols
}

/**
 * 审批详情
 * @param row
 */
const onNeedViewApp = (row?: TypedAny) => {
  if (row) {
    const records = gridRef.value?.getCheckboxRecords(true) || []
    const cans = records.filter((f) => f?.wfRuning?.can_approval)
    const running_id = getNotEmpty(row, ['wf_runingid', 'objectId'])
    const ids = cans.map((v) => getNotEmpty(v, ['wf_runingid', 'objectId']))

    const list = ids.includes(running_id) ? ids : [running_id]

    mittBus.emit('onNeedViewApp', {
      list: list,
      running_id,
      onFetch
    })
  }
}

/**
 * 是否禁用
 * @param action
 * @param row
 */
const onActionHide = (action: BusinessUIAction, row: TypedAny) => {
  if (props.wfDesign) {
    if (['can_submit', 'can_un_submit'].includes(action.action)) {
      const wfRun = row.wfRuning
      if (wfRun) {
        return wfRun[action.action]
      } else {
        return true
      }
    } else if (['Udp', 'Del'].includes(action.action)) {
      const wfRun = row.wfRuning
      return wfRun['can_submit']
    } else {
      return true
    }
  } else {
    return true
  }
}

/**
 * 打开全局表单
 * @param isForm
 * @param row
 */
const onTemplateForm = (isForm: boolean = true, row?: TypedAny) => {
  const $dialog = unref(formDialogRef)
  if (!$dialog) return
  $dialog.open({
    onFetch,
    row,
    uiTable: props.uiTable,
    uiForm: props.uiForm,
    dicTable: props.dicTable,
    action: unref(currentAction),
    isForm
  })
}

/**
 * 撤回工作流
 */
const onCanUnSubmit = () => {
  openMessageBox().then((done: any) => {
    if (!currentRow) return
    WorkFlowRuingDel(currentRow.wf_runingid).then(() => {
      if (done) done()
      mittBus.emit('onUpdateMsgDot')
      ElMessage.success(`${currentAction?.name || ''} 成功`)
    })
  })
}

/**
 * 删除
 */
const onRemoveRow = () => {
  if (!currentRow) return
  const edit_render = props.uiTable?.edit_render
  const isBatchSave = props.uiActions?.some((f) => f.action === 'BatchSave')
  // 如果有批量保存按钮，将删除按钮变成静默删除。（统一保存）
  if (edit_render && isBatchSave) {
    const key = currentRow[unref(keyField)]
    if (!isGridRowId(key)) deleteMap.set(key, currentRow)
    gridRef.value?.remove(currentRow)
  } else {
    // 没有批量删除就，单个直接弹窗确认后删除。
    openMessageBox().then((done: any) => {
      if (!props.uiForm || !currentRow) return
      CustomRequest({
        url: props.uiForm.api,
        method: 'delete',
        params: {
          id: currentRow[unref(keyField)]
        }
      }).then(({ data }) => {
        if (data && data.forms && data.forms.length) {
          // 把数据发送给父级
          mittBus.emit('onUpdateParent', data)
        }
        done()
      })
    })
  }
}

/**
 * 提交工作流
 * @param userId
 */
const onCanSubmit = (userId?: string) => {
  if (userId !== 'close') {
    openMessageBox().then((done: any) => {
      WorkFlowRuingStart({
        instanceName: props.wfDesign?.instanceName,
        flag: props.wfDesign?.flag,
        remark: '',
        approvalUsersId: userId ? [userId] : [],
        sendMsg: false,
        sendSms: false,
        multApp: false,
        instanceId: currentRow ? currentRow[unref(keyField)] : ''
      })
        .then(() => {
          if (done) done()
          mittBus.emit('onUpdateMsgDot')
          ElMessage.success(`${currentAction?.name || ''} 成功`)
        })
        .catch(() => {
          if (done) done()
        })
    })
  }
}

/**
 * 工作流提交
 */
const onActionRuingNext = () => {
  if (currentRow && props.wfDesign) {
    mittBus.emit('onOpenRuingNext', {
      params: {
        instanceName: props.wfDesign.instanceName,
        instanceId: currentRow[unref(keyField)],
        flag: props.wfDesign.flag
      },
      callback: onCanSubmit
    })
  }
}

/**
 * 按钮获取父级参数
 * 优先级 => 行>父级表单>查询栏
 */
const onActionParentParams = () => {
  const action = unref(currentAction)
  const row = unref(currentRow)
  const params = props.params || {}
  const param = row || params || {}
  if (action) {
    const default_value_parse = action.default_value_parse
    for (const key in default_value_parse) {
      const value1 = param[key] || default_value_parse[key]
      const value2 = params[key] || default_value_parse[key]
      if (value1 !== undefined && value1 !== '') {
        default_value_parse[key] = value1
      } else {
        // 否则看查询参数里面有没有
        default_value_parse[key] = value2
      }
    }
  }
}

/**
 * 表格行内编辑 - 批量校验
 * @param list 批量校验的数据
 */
const onBatchVerify = async (list: TypedAny[]) => {
  const $grid = unref(gridRef)
  if (!$grid) return Promise.resolve(true)
  const errMap = await $grid.validate(list)
  if (errMap) {
    const verify: string[] = []
    const values = Object.values(errMap)
    values.forEach((arr) => {
      arr.forEach((a) => {
        if (a.rule.content) verify.push(a.rule.content)
      })
    })
    ElMessage.warning(verify.join('，'))
    return Promise.reject(false)
  } else {
    return Promise.resolve(true)
  }
}

/**
 * 获取表格编辑过的所有行
 */
const getUpdateRows = (): { del: any[]; upd: any[] } => {
  const $grid = unref(gridRef)
  if (!$grid) return { del: [], upd: [] }
  const updateRecords = $grid.getUpdateRecords()
  const insertRecords = $grid.getInsertRecords()
  const deleteRecords = Array.from(deleteMap).map(([, value]) => value)
  const upd = [...insertRecords, ...updateRecords]
  return {
    del: deleteRecords,
    upd
  }
}

/**
 * 行内编辑的批量保存
 */
const onBatchSave = async () => {
  const keyField = props.uiTable?.default_value_parse.keyField || 'id'
  const { del, upd } = getUpdateRows()
  if (!del.length && !upd.length) {
    ElMessage.warning('没有可以保存的数据')
    return Promise.resolve(false)
  }
  try {
    // 批量校验
    await onBatchVerify(upd)

    btnLoading.value = true

    upd.forEach((v) => {
      const key = v[keyField]
      if (key && isGridRowId(key)) {
        v[keyField] = undefined
      }
      for (const k in v) {
        if (v[k] === null) {
          delete v[k]
        }
      }
    })
    const api = props.uiTable?.api
    await CustomRequest({
      url: api,
      method: 'put',
      params: props.params,
      data: { del, upd }
    })
    await onFetch()
    ElMessage.success('保存成功')
    btnLoading.value = false
  } catch (e) {
    btnLoading.value = false
  }
}

/**
 * 行内编辑的批量删除
 */
const onBatchDelete = () => {
  const $grid = unref(gridRef)
  if (!$grid) return
  const records = $grid.getCheckboxRecords(true)
  const reserveRecords = $grid.getCheckboxReserveRecords(true)
  const delRecords = records.concat(reserveRecords)
  if (!delRecords.length) {
    ElMessage.warning('未勾选')
    return Promise.resolve(false)
  }
  delRecords.forEach((v) => {
    const key = v[unref(keyField)]
    if (!isGridRowId(key)) deleteMap.set(key, v)
  })
  $grid.remove(delRecords)
}

/**
 * 操作
 * @param action
 * @param row
 */
const onAction = (action: BusinessUIAction, row?: TypedAny) => {
  currentRow = row
  currentAction = action
  onActionParentParams()
  if (action.action === 'Add') {
    onTemplateForm(true)
  } else if (action.action === 'Insert') {
    onInsertEvent()
  } else if (action.action === 'Udp') {
    onTemplateForm(true, row)
  } else if (action.action === 'BatchSave') {
    onBatchSave()
  } else if (action.action === 'BatchDelete') {
    onBatchDelete()
  } else if (action.action === 'SetUser') {
    onActionSetUser(row)
  } else if (action.action === 'can_submit') {
    onActionRuingNext()
  } else if (action.action === 'can_un_submit') {
    onCanUnSubmit()
  } else if (action.action === 'App') {
    onNeedViewApp(row)
  } else if (action.action === 'Del') {
    onRemoveRow()
  } else if (action.action === 'RPwd') {
    onActionResetPwd()
  } else if (action.action === 'TableSelector') {
    onActionOpenPage('TableSelector')
  } else if (action.action === 'Deduction') {
    onActionOpenPage('TemplateDeduction')
  } else if (action.action === 'Overtime') {
    onActionOpenPage('TemplateOvertime')
  } else if (action.model === 'business') {
    onActionOpenPage('TemplateGrid')
  } else if (action.model === 'form') {
    onActionOpenPage('TemplateForm')
  } else if (action.action === 'Print') {
    onActionOpenPage('TemplatePrint')
  } else if (action.action === 'ImportJson') {
    onActionImportJson()
  } else if (action.model === 'download') {
    onActionDownload()
  } else if (action.action === 'ImportExcel') {
    onActionImportExcel()
  } else if (action.api) {
    onActionRequest()
  }
}

/**
 * 弹窗
 */
const onActionOpenPage = (key: string) => {
  const action = unref(currentAction)
  let row = null
  if (action?.action === 'Print') {
    const $grid = gridRef.value
    row = $grid?.getRadioRecord(true)
    if (!row) {
      ElMessage.warning('请勾选需要打印的行')
      return
    }
  }
  gridDialogRef.value.open(key, {
    id: action?.business_id,
    title: action?.name,
    action,
    params: props.params,
    row
  })
}

/**
 * 重置密码
 */
const onActionResetPwd = () => {
  const row = unref(currentRow)
  if (row) {
    mittBus.emit('onOpenChangePass', {
      mode: false,
      callback({ params, close }: TypedAny) {
        onActionRequest({
          pwd: params.new_pwd,
          user_id: row[unref(keyField)]
        }).then(close)
      }
    })
  }
}

/**
 * 按钮请求
 */
const onActionRequest = async (params?: TypedAny) => {
  const action = unref(currentAction)
  const config = {
    url: action?.api,
    method: action?.method || 'post',
    params: {},
    data: {}
  }
  const action_parse = clone(action?.default_value_parse || {}, true)
  const c_params = clone(params || {}, true)
  const default_value_parse = assign(action_parse, c_params)
  if (!params) {
    const radio = gridRef.value?.getRadioRecord()
    const records = gridRef.value?.getCheckboxRecords() || []
    if (radio) {
      default_value_parse.row = radio[unref(keyField)] || undefined
    } else if (records.length) {
      if (['get', 'delete'].includes(config.method)) {
        // 字符串传参
        default_value_parse.rows = records.map((v: TypedAny) => v[unref(keyField)]).join(',')
      } else {
        // 数组传参
        default_value_parse.rows = records.map((v: TypedAny) => v[unref(keyField)])
      }
    } else if (action?.model === 'trigger') {
      ElMessage.warning('未勾选')
      return Promise.resolve()
    }
  }
  // 确认框
  let close: Fn | undefined
  if (action?.confirm) {
    close = await openMessageBox()
  }
  // if (['get', 'delete'].includes(config.method)) {
  //   config.params = default_value_parse
  // } else {
  //   config.data = default_value_parse
  // }
  config.params = default_value_parse
  config.data = default_value_parse

  return CustomRequest(config)
    .then(({ data }) => {
      if (action?.action === 'ExportJson') {
        gridRef.value?.saveFile({
          filename: route.meta.title || 'JSON',
          type: 'json',
          content: JSON.stringify({ rows: data })
        })
      } else if (action?.model === 'trigger' && props.params) {
        emit('close', true)
      } else {
        onFetch()
      }
      ElMessage.success(`${action?.name} 成功`)
    })
    .finally(() => {
      close && close()
      modelValue.value = false
    })
}

/**
 * 插入行
 * @param list
 */
const onInsertEvent = async (list?: TypedAny[]) => {
  const $grid = gridRef.value
  if ($grid) {
    if (list) {
      const records = list.map((v) => assign({}, v, props.params))
      await $grid.insertAt(records, -1)
    } else {
      const record = assign({}, props.params)
      await $grid.insertAt(record, -1)
    }
  }
}

/**
 * 导入Excel
 */
const onActionImportExcel = async () => {
  const $grid = unref(gridRef)
  if (!$grid) return
  const { file } = await $grid.readFile({ multiple: false, types: ['xlsx', 'xls'] })
  if (file) {
    const { headers, data } = await readExcelFile(file)
    const items = props.uiForm?.items || []
    const columns = props.uiTable?.columns || []
    const headerForms = headers.map((v) =>
      items.find((f) => {
        const column = columns.find((c) => c.field === f.field || c.field === f.rel_item)
        return f.title === v || (column && column.title === v)
      })
    )

    // 下面是拉取系统数据和导入的数据进行匹配（谨慎修改）
    const list: TypedAny[] = []
    const state: StateInterface = {}
    await onComponentServerFetch(items, state, props.params || {}, {})
    await onInitApiData(items, state, props.params || {}, {})
    onInitDicData(items, state, props.dicTable || [])
    headerForms.forEach((form, formIndex) => {
      if (form) {
        const elComponent = form.elComponent || ''
        for (let i = 0; i < data.length; i++) {
          const row = list[i] || setFormDefaultParams(items, {})
          const rowValues = data[i]
          if (rowValues) {
            const field = form.rel_item || form.field
            const cellValue = rowValues[formIndex]
            const options = state[form.field] || state[form.component]
            if (options && options.length) {
              const item = options.find((f) => f.label === cellValue)
              row[field] = cellValue
              if (item) row[form.field] = item.value
            } else if (['el-date-picker'].includes(elComponent)) {
              if (cellValue) {
                const date = String(cellValue)
                row[field] = dayjs(date).format('YYYY-MM-DD')
              }
            } else if (['el-select'].includes(form.component)) {
              if (cellValue) row[field] = cellValue
            } else {
              if (cellValue) row[field] = cellValue
            }
          }
          list[i] = row
        }
      }
    })
    // 批量插入行内
    await onInsertEvent(list)
  }
}

/**
 * 导入JSON（格式化好丢给后台自己处理）
 */
const onActionImportJson = async () => {
  const $grid = unref(gridRef)
  if (!$grid) return
  const action = unref(currentAction)
  const { file } = await $grid.readFile({ multiple: false })
  if (file) {
    const reader = new FileReader()
    reader.onload = ({ target }: ProgressEvent<FileReader>) => {
      if (target && target.result) {
        try {
          const jsonContent = JSON.parse(String(target.result))
          const config = {
            url: action?.api,
            method: action?.method || 'post',
            params: {},
            data: jsonContent
          }
          modelValue.value = true
          CustomRequest(config)
            .then(() => {
              ElMessage.success(`${action?.name} 成功`)
              onFetch()
            })
            .finally(() => {
              modelValue.value = false
            })
        } catch (e) {
          ElMessage.warning('文件处理失败')
        }
      }
    }
    reader.readAsText(file)
  }
}

/**
 * 按钮下载（需要菜单配置里面，给按钮上传需要下载的文件）
 */
const onActionDownload = () => {
  const action = unref(currentAction)
  if (action) {
    const id = action.default_value_parse.downFileId
    if (id) {
      GetBaseFile(id).then(({ data }) => {
        GetBaseFileDown(id).then((blobData: any) => {
          if (action.action === 'ExportWord') {
            onActionDownloadWord(data, blobData)
          } else {
            onActionDownloadFile(data, blobData)
          }
        })
      })
    }
  }
}

/**
 * 生成word并下载
 * @param fileData
 * @param blobData
 */
const onActionDownloadWord = async (fileData: BusinessUIFile, blobData: any) => {
  const row = unref(currentRow)
  const action = unref(currentAction)
  if (!action) return ElMessage.warning('未获取按钮数据')
  if (!row) return ElMessage.warning('未获取到行数据')
  const keyField = props.uiTable?.default_value_parse.keyField || 'id'
  const id = row[keyField]
  let config = {
    url: '',
    method: 'get',
    params: { id }
  }
  if (action.api) {
    config.url = action.api
    config.method = action.method || 'get'
  } else if (id) {
    config.url = props.uiForm?.api || '/'
    config.method = 'get'
  }
  const { data } = await CustomRequest<TypedAny>(config)
  data['fileName'] = fileData.fileName
  readerWordData(blobData, data)
}

/**
 * 直接下载
 * @param fileData
 * @param blobData
 */
const onActionDownloadFile = (fileData: BusinessUIFile, blobData: any) => {
  const objectUrl = URL.createObjectURL(blobData)
  let link = document.createElement('a')
  link.style.display = 'none'
  link.href = objectUrl
  link.setAttribute('download', fileData.fileName)
  document.body.appendChild(link)
  link.click()
  URL.revokeObjectURL(objectUrl) // 释放内存
}

/**
 * 打开用户（统一系统账户选择器）
 * @param row
 */
const onActionSetUser = (row?: TypedAny) => {
  if (row && props.uiForm) {
    CustomRequest({
      url: props.uiForm.api,
      method: 'get',
      params: {
        id: row[unref(keyField)]
      }
    }).then(({ data }) => {
      mittBus.emit('onOpenSelectUser', {
        rows: data.users_id || [],
        callback: (userId: string[] | string) => {
          if (props.uiTable) {
            if (props.uiTable.id === 'sys_workflow_role' && isArray(userId)) {
              WorkFlowRoleSetUsers({
                id: currentRow ? currentRow[unref(keyField)] : '',
                rows: userId
              }).then(() => {
                ElMessage.success('配置成功')
                onFetch()
              })
            } else if (props.uiTable.id === 'sys_role' && isArray(userId)) {
              PutBaseRoleSetUsers({
                roleId: currentRow ? currentRow[unref(keyField)] : '',
                usersId: userId
              }).then(() => {
                ElMessage.success('配置成功')
                onFetch()
              })
            }
          }
        }
      })
      // userRef.value.open(true, data.users_id || [])
    })
  }
}

/**
 * 双击表格（有则默认打开详情）
 */
const onCellDblclick: VxeTableEvents.CellDblclick = ({ row, column }) => {
  if (!props.uiForm) return
  if (props.uiTable?.edit_render) return
  if (!row[unref(keyField)]) return
  if (props.uiForm.api) {
    if (!['radio', 'checkbox'].includes(column.type || '')) onTemplateForm(false, row)
  }
}

/**
 * 单选
 */
const onRadioChange: VxeTableEvents.RadioChange<TypedAny> = (item) => {
  emit('radio-change', item)
}

/**
 * 保存列配置
 * @param $grid
 */
const setCustomColumns = ($grid: VxeGridConstructor) => {
  if (props.uiTable) {
    const { fullColumn } = $grid.getTableColumn()
    const cols = fullColumn
      .filter((column) => columnFilterMethod({ column }))
      .map((v, seq) => {
        return {
          type: v.type,
          field: v.field,
          fixed: v.fixed,
          visible: v.visible,
          width: v.renderWidth,
          seq
        }
      })
    setGridColumns(props.uiTable, cols)
  }
}

// 列表配置变化
const onCustomChange = ({ $grid, type }: VxeGridDefines.CustomEventParams) => {
  if (props.uiTable) {
    if (type === 'reset') {
      removeGridColumns(props.uiTable)
      onFetch()
    } else if (type === 'confirm') {
      setCustomColumns($grid)
    }
  }
}

// 列表被拖动
const onResizableChange = ({ $grid }: VxeGridDefines.ResizableChangeEventParams) => {
  if (props.uiTable) {
    setCustomColumns($grid)
  }
}

// // 做联动的时候用得到（暂时不做）
// const onEditActivated = async ({ row, $grid }: VxeGridDefines.EditActivatedEventParams) => {
//   if (props.uiForm) {
//     const items = props.uiForm.items || []
//     const state: TypedAny<SelectOptionType[]> = {}
//     const params = props.params || {}
//     const renderComponents = props.uiForm.items.filter((f) =>
//       edit_render_components.includes(f.elComponent || '')
//     )
//     await onComponentServerFetch(renderComponents, state, params, row)
//     await onInitApiData(renderComponents, state, params, row)
//
//     const columns = $grid.getColumns()
//     columns.forEach((v) => {
//       const form = items.find((f) => (f.field === v.field || f.rel_item === v.field))
//       if (form) {
//         const list = state[form.field] || state[form.component]
//         if (list) {
//           if (['el-tree-select'].includes(form.elComponent || '') && v.editRender.props) {
//             v.editRender.props['options'] = list
//           } else {
//             v.editRender.options = list
//           }
//         }
//       }
//     })
//   }
// }

// 暴露内部xGrid实例
const getInstance = (): VxeGridInstance | undefined => {
  return unref(gridRef)
}

// 表格配置改变，重新初始化
watch(
  () => props.uiTable,
  (option) => {
    if (option) initGridOptions()
  },
  { immediate: true }
)

defineExpose({ initGridOptions, onFetch, getInstance, getUpdateRows })
</script>

<template>
  <div v-if="uiTable" :class="{ 'layout-padding': !insert }">
    <!--@close="emit('close')"-->
    <!-- 扩展组件 -->
    <TemplateFormDialog ref="formDialogRef" :params="params" @fetch="onFetch" />
    <TemplateGridDialog
      ref="gridDialogRef"
      :params="params"
      :ui-form="uiForm"
      :dic-table="dicTable"
      @close="emit('close')"
      @fetch="onFetch"
    />
    <vxe-toolbar ref="toolbarRef" v-bind="toolbarConfig">
      <template #buttons>
        <slot>
          <TemplateQuery
            ref="queryRef"
            v-model="modelValue"
            :ui-query="uiQuery"
            :ui-actions="uiActions"
            :wf-design="wfDesign"
            :dic-query="dicQuery"
            :right-spacing="rightSpacing"
            :btn-loading="btnLoading"
            @action="onAction"
            @fetch="onToolFetch"
            :show-actions="showActions"
            :class="{ 'box-shadow': boxShadow }"
          >
            <template #query_tool>
              <slot name="query_tool"></slot>
            </template>
            <template #query_default>
              <slot name="query_default"></slot>
            </template>
          </TemplateQuery>
        </slot>
      </template>
    </vxe-toolbar>
    <div class="layout-padding-auto layout-padding-view" :class="{ 'box-shadow': boxShadow }">
      <vxe-grid
        ref="gridRef"
        key="id"
        v-bind="gridOptions"
        :loading="modelValue"
        :height="height || insert ? undefined : 'auto'"
        :empty-text="emptyText"
        @custom="onCustomChange"
        @resizable-change="onResizableChange"
        @cell-dblclick="onCellDblclick"
        @radio-change="onRadioChange"
      >
        <!-- 审批详情 -->
        <template #wf_node="{ row, column }">
          <el-link
            v-if="row[column.field]"
            :type="row[`${column.field}_display_type`] || 'info'"
            @click="onNeedViewApp(row)"
            class="cursor-pointer"
          >
            {{ row[column.field] }}
          </el-link>
        </template>
        <!-- 标签 -->
        <template #el_tag="{ row, column }">
          <el-tag :type="row[`${column.field}_display_type`] || 'info'">
            {{ row[column.field] }}
          </el-tag>
        </template>
        <!-- 操作 -->
        <template #action="{ row }">
          <el-space :size="5">
            <template v-for="(action, index) in embeddedUIActions">
              <el-button
                v-if="onActionHide(action, row)"
                size="small"
                :key="index"
                :type="action.type || 'default'"
                :disabled="action.action === 'finish' ? row[action.action] === '是' : false"
                :class="{
                  'opacity-0-3': action.action === 'finish' ? row[action.action] === '是' : false
                }"
                @click="onAction(action, row)"
                link
              >
                {{ action.name }}
              </el-button>
            </template>
          </el-space>
        </template>
        <!-- pager 插槽-->
        <template #pager v-if="uiTable.pagination">
          <vxe-pager
            :layouts="
              mobile
                ? ['PrevJump', 'PrevPage', 'Number', 'NextPage', 'Total']
                : [
                    'Sizes',
                    'PrevJump',
                    'PrevPage',
                    'Number',
                    'NextPage',
                    'NextJump',
                    'FullJump',
                    'Total'
                  ]
            "
            v-model:current-page="gridPage.page"
            v-model:page-size="gridPage.pageSize"
            :total="gridPage.total"
            @page-change="onFetch()"
          >
          </vxe-pager>
        </template>
      </vxe-grid>
    </div>
  </div>
  <div v-else class="text-center">
    <el-empty description="该业务没有数据" :image-size="40" />
    <!--    <router-link to="/system/business/menu">-->
    <!--      <el-button>去菜单管理</el-button>-->
    <!--    </router-link>-->
  </div>
</template>
